package cn.net.wanji.job;

import cn.net.wanji.entity.CongestionDataParam;
import cn.net.wanji.entity.CongestionVehicle;
import cn.net.wanji.mapper.MonitorMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j(topic = "定时刷新拥堵信息【ServiceConfigJob】")
@EnableScheduling
@Configuration
public class RefreshCongestionDataJob {
    public int region1 = 0;//区域1拥堵状态
    public int region2 = 0;//区域2拥堵状态
    public int region3 = 0;//区域3拥堵状态
    public int region4 = 0;//区域4拥堵状态
    public int region5 = 0;//区域5拥堵状态
    public int region6 = 0;//区域6拥堵状态
    public int region7 = 0;//区域7拥堵状态

    List<Double> region1Speed = new ArrayList<>();
    List<Double> region2Speed = new ArrayList<>();
    List<Double> region3Speed = new ArrayList<>();
    List<Double> region4Speed = new ArrayList<>();
    List<Double> region5Speed = new ArrayList<>();
    List<Double> region6Speed = new ArrayList<>();
    List<Double> region7Speed = new ArrayList<>();


    @Autowired
    private MonitorMapper monitorMapper;

    @Value("${congestion.time}")
    private String time;

    @Scheduled(fixedRateString = "${congestion.executeTime}")
    public void RefreshCongestionData() throws ParseException {
        region1Speed = new ArrayList<>();
        region2Speed = new ArrayList<>();
        region3Speed = new ArrayList<>();
        region4Speed = new ArrayList<>();
        region5Speed = new ArrayList<>();
        region6Speed = new ArrayList<>();
        region7Speed = new ArrayList<>();

        //查询一段时间内拥堵数据车辆列表
        LocalDateTime currentDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String endTime = currentDateTime.format(formatter);
//        Integer.parseInt(time);
        String startTime = currentDateTime.minusMinutes(Long.parseLong("120")).format(formatter);
        CongestionDataParam firstCongestionData = new CongestionDataParam();
        firstCongestionData.setStartTime(startTime);
        firstCongestionData.setEndTime(endTime);
        firstCongestionData.setErId("S001933030055210010");
        // 获取第一个门架的数据
        List<CongestionVehicle> congestionVehicleFirstList = monitorMapper.selectCongestionVehicleList(firstCongestionData);
        HashMap<String, CongestionVehicle> firstHashMap = congestionVehicleFirstList.stream()
                .collect(Collectors.toMap(CongestionVehicle::getEtcLicense, congestionVehicle
                        -> congestionVehicle, (a, b) -> b, HashMap::new));
        CongestionDataParam finalCongestionData = new CongestionDataParam();
        finalCongestionData.setStartTime(startTime);
        finalCongestionData.setEndTime(endTime);
        finalCongestionData.setErId("S001933030055210017");
        List<CongestionVehicle> congestionVehicleFinalList = monitorMapper.selectCongestionVehicleList(finalCongestionData);
        HashMap<String, CongestionVehicle> finalHashMap = congestionVehicleFinalList.stream()
                .collect(Collectors.toMap(CongestionVehicle::getEtcLicense, congestionVehicle
                        -> congestionVehicle, (a, b) -> b, HashMap::new));
        ArrayList<String> firstData = new ArrayList<>();
        List<CongestionVehicle> firstVehicle = new ArrayList<>();
        for (Map.Entry<String, CongestionVehicle> entry : firstHashMap.entrySet()) {
            if (!finalHashMap.containsKey(entry.getKey())) {
                firstData.add(entry.getKey());
                firstVehicle.add(entry.getValue());
            }
        }
        CongestionDataParam congestionData = new CongestionDataParam();
        String driveTime = currentDateTime.minusSeconds(Long.parseLong(time)).format(formatter);
        congestionData.setStartTime(driveTime);
        congestionData.setEndTime(endTime);
        List<CongestionVehicle> congestionVehicles = monitorMapper.selectCongestionVehicleDriveList(congestionData);
        ArrayList<CongestionVehicle> congestionVehiclesList = congestionVehicles.stream()
                .filter(congestionVehicle -> firstData.contains(congestionVehicle.getEtcLicense()))
                .collect(Collectors.toCollection(ArrayList::new));
        Map<String, List<CongestionVehicle>> filtered = filterVehicle(firstVehicle, congestionVehiclesList);

        // 根据
        //过滤异常拥堵车辆列表数据
        // Map<String, List<CongestionVehicle>> filterCongestionVehicleList = filterCongestionVehicle(congestionVehicleFirstList);
        //推算出每辆车通过对应门架的速度 针对每组车辆数据 计算平均速度放入数组中
        getVehicleSpeed(filtered);
        //根据数组计算出拥堵状态
        region1 = getCongestionStatus(region1Speed, 1);
        region2 = getCongestionStatus(region2Speed, 2);
        region3 = getCongestionStatus(region3Speed, 3);
        region4 = getCongestionStatus(region4Speed, 4);
        region5 = getCongestionStatus(region5Speed, 5);
        region6 = getCongestionStatus(region6Speed, 6);
        region7 = getCongestionStatus(region7Speed, 7);
    }


    /**
     * 获取门架号
     *
     * @param erId
     * @return
     */
    public int getErNum(String erId) {
        switch (erId) {
            case "S001933030055210010":
                return 1;
            case "S001933030055210011":
                return 2;
            case "S001933030055210012":
                return 3;
            case "S001933030055210013":
                return 4;
            case "S001933030055210014":
                return 5;
            case "S001933030055210015":
                return 6;
            case "S001933030055210016":
                return 7;
            case "S001933030055210017":
                return 8;
            default:
                return 0;
        }
    }

    /**
     * 获取区域距离
     *
     * @param regionNum
     * @return
     */
    public int getRegionDistance(int regionNum) {
        switch (regionNum) {
            case 1:
                return 520;
            case 2:
                return 520;
            case 3:
                return 520;
            case 4:
                return 520;
            case 5:
                return 520;
            case 6:
                return 670;
            case 7:
                return 350;
            default:
                return 0;
        }
    }

    /**
     * 过滤异常拥堵车辆列表数据
     *
     * @param congestionVehicleList 拥堵车辆列表数据
     * @return 清洗后的拥堵车辆列表数据
     */
    public Map<String, List<CongestionVehicle>> filterCongestionVehicle(List<CongestionVehicle> congestionVehicleList) throws ParseException {
        //将门架编码增加门架号以及Data类型时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //用formatter格式化当前时间
        for (CongestionVehicle congestionVehicle : congestionVehicleList) {
            congestionVehicle.setErNum(getErNum(congestionVehicle.getErId()));
            //congestionVehicle.getEtcTransTime转Date
            congestionVehicle.setEtcTransDate(sdf.parse(congestionVehicle.getEtcTransTime()));
        }
        //用Stream对congestionVehicleList根据etcLicense进行分组并按照etcTransData进行升序排序
        Map<String, List<CongestionVehicle>> collect = congestionVehicleList.stream().collect(Collectors.groupingBy(CongestionVehicle::getEtcLicense));
        //再对门架号进行循环判断 相邻两个门架号 前一个大于后一个则删除前一个
        Map<String, List<CongestionVehicle>> filterCongestionVehicleList = new HashMap<>();
        for (Map.Entry<String, List<CongestionVehicle>> entry : collect.entrySet()) {
            List<CongestionVehicle> value = entry.getValue();
            for (int i = 0; i < value.size() - 1; i++) {
                if (value.get(i).getErNum() > value.get(i + 1).getErNum()) {
                    value.remove(i);
                }
            }
            filterCongestionVehicleList.put(entry.getKey(), value);
        }
        //将collect转成list
        List<CongestionVehicle> collect1 = collect.values().stream().flatMap(List::stream).collect(Collectors.toList());
        List<CongestionVehicle> filterCongestionVehicleList1 = filterCongestionVehicleList.values().stream().flatMap(List::stream).collect(Collectors.toList());
        System.out.println("过滤数据前：" + collect1.size() + "过滤数据后：" + filterCongestionVehicleList1.size() + "过滤数据条数：" + (collect1.size() - filterCongestionVehicleList1.size()));
        return filterCongestionVehicleList;
    }

    public Map<String, List<CongestionVehicle>> filterVehicle(List<CongestionVehicle> firstVehicle,
                                                              List<CongestionVehicle> vehicleList) throws ParseException {
        //将门架编码增加门架号以及Data类型时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        vehicleList.addAll(firstVehicle);
        //用formatter格式化当前时间
        for (CongestionVehicle congestionVehicle : vehicleList) {
            congestionVehicle.setErNum(getErNum(congestionVehicle.getErId()));
            //congestionVehicle.getEtcTransTime转Date
            congestionVehicle.setEtcTransDate(sdf.parse(congestionVehicle.getEtcTransTime()));
        }
        //用Stream对congestionVehicleList根据etcLicense进行分组并按照etcTransData进行升序排序
        Map<String, List<CongestionVehicle>> collect = vehicleList.stream().collect(Collectors.groupingBy(CongestionVehicle::getEtcLicense));
        //再对门架号进行循环判断 相邻两个门架号 前一个大于后一个则删除前一个
        Map<String, List<CongestionVehicle>> filterCongestionVehicleList = new HashMap<>();
        for (Map.Entry<String, List<CongestionVehicle>> entry : collect.entrySet()) {
            List<CongestionVehicle> value = entry.getValue();
            for (int i = 0; i < value.size() - 1; i++) {
                if (value.get(i).getErNum() > value.get(i + 1).getErNum()) {
                    value.remove(i);
                }
            }
            if (value.size() > 1) {
                filterCongestionVehicleList.put(entry.getKey(), value);
            } else {
                filterCongestionVehicleList.remove(entry.getKey());
            }
        }
        log.info("数据处理前共：{}条，数据处理后共：{}条", collect.size(), filterCongestionVehicleList.size());
        return filterCongestionVehicleList;
    }

    /**
     * 推算出每辆车通过对应门架的速度
     *
     * @param filterCongestionVehicleList 拥堵车辆列表数据
     * @return
     */
    public void getVehicleSpeed(Map<String, List<CongestionVehicle>> filterCongestionVehicleList) {
        for (Map.Entry<String, List<CongestionVehicle>> entry : filterCongestionVehicleList.entrySet()) {
            //比较相邻两个门架的时间差
            List<CongestionVehicle> value = entry.getValue();
            HashMap<String, CongestionVehicle> congestionVehicleMap = new HashMap<>();
            ArrayList<String> erList = new ArrayList<>();
            for (CongestionVehicle congestionVehicle : value) {
                erList.add(congestionVehicle.getErId());
                congestionVehicleMap.put(congestionVehicle.getErId(), congestionVehicle);
            }
            Collections.sort(erList);
//            System.out.println(erList);
            for (int i = 0; i < erList.size() - 1; i++) {
                getSpeed(getErNum(erList.get(i)), getErNum(erList.get(i + 1)),
                        congestionVehicleMap.get(erList.get(i)).getEtcTransDate(),
                        congestionVehicleMap.get(erList.get(i + 1)).getEtcTransDate());
            }
            //getSpeed(value.get(i).getErNum(), value.get(i + 1).getErNum(), value.get(i).getEtcTransDate(), value.get(i + 1).getEtcTransDate());

        }
    }


    /**
     * 计算两个门架间车辆速度 并将车辆速度放入到对应的区域速度数组中
     *
     * @param startErNum
     * @param endErNum
     * @param startTime
     * @param endTime
     */
    public void getSpeed(int startErNum, int endErNum, Date startTime, Date endTime) {
        //获取俩门架之间的区域id并累加距离
        List<Integer> regionList = getRegionList(startErNum, endErNum);
        int distance = regionList.stream().mapToInt(this::getRegionDistance).sum();
        //计算时间差
        long time = endTime.getTime() - startTime.getTime();
        if (time == 0) {
            return;
        }
        //计算速度(km/h)(脏数据超过150不要了)
        double speed = (distance / (time / 1000)) * 3.6;
        if (speed > 150) {
            return;
        }
        if (speed < 0) {
            return;
        }
//        System.out.println("计算速度(km/h)"+speed);
        for (Integer region : regionList) {
            switch (region) {
                case 1:
                    region1Speed.add(speed);
                    break;
                case 2:
                    region2Speed.add(speed);
                    break;
                case 3:
                    region3Speed.add(speed);
                    break;
                case 4:
                    region4Speed.add(speed);
                    break;
                case 5:
                    region5Speed.add(speed);
                    break;
                case 6:
                    region6Speed.add(speed);
                    break;
                case 7:
                    region7Speed.add(speed);
                    break;
                default:
                    break;
            }
        }
    }

    //获取两个整数之间的数
    public List<Integer> getRegionList(int start, int end) {
        List<Integer> integerList = new ArrayList<>();
        for (int i = start; i < end; i++) {
            integerList.add(i);
        }
        return integerList;
    }


    /**
     * 通过 区域车辆数 和 平均车速 判断拥堵状态
     *
     * @param regionSpeedList 区域平均车速列表
     * @return
     */
    public int getCongestionStatus(List<Double> regionSpeedList, Integer area) {
        if (regionSpeedList.size() > 0) {
            //计算区域平均车速
            double regionAverageSpeed = regionSpeedList.stream().mapToDouble(Double::doubleValue).average().getAsDouble();
//            System.out.println("平均速度：" + regionAverageSpeed);
            if (regionAverageSpeed > 60) {
                //>60km/h:畅通
                return 0;
            } else if (regionAverageSpeed >= 40 && regionAverageSpeed < 60) {
                //[40km/h，60km/h):轻度拥堵口
                log.info("区域{}，发生轻度拥堵", area);
                return 1;
            } else if (regionAverageSpeed >= 20 && regionAverageSpeed < 40) {
                // [20km/h，40km/h):中度拥堵口
                log.info("区域{}，中度拥堵口", area);
                return 2;
            } else if (regionAverageSpeed >= 0 && regionAverageSpeed < 20) {
                // [00km/h，20km/h):严重拥堵
                log.info("区域{}，严重拥堵", area);
                return 3;
            }
        } else {
            return 0;
        }
        return 0;
    }

    public static void main(String[] args) {
        LocalDateTime currentDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String endTime = currentDateTime.format(formatter);
//        Integer.parseInt(time);
        String startTime = currentDateTime.minusSeconds(Long.parseLong("40")).format(formatter);
        System.out.println(startTime);
        System.out.println(endTime);
    }

}
